home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet Info 1994 March
/
Internet Info CD-ROM (Walnut Creek) (March 1994).iso
/
networking
/
ip
/
ka9q
/
net_des.arc
/
RADLOGIN.C
< prev
next >
Wrap
C/C++ Source or Header
|
1987-02-28
|
4KB
|
146 lines
/*
* Secure packet radio login command. The system first prompts for the
* user's name. It then generates and sends a unique "challenge" (a 64-bit
* hexadecimal integer) based on the time of day. The user encrypts
* this value using the Data Encryption Standard and his private key and
* type it back to the system. The system also encrypts the challenge
* with the user's key and compares the two. If they match, he's in.
*
* 18 December 1986 Phil Karn, KA9Q
*
* mods:
* 870318 Bdale, N3EUA Add code to run user's .login commands.
* 870317 Bdale, N3EUA Hacked to remove putenv() by calling execle()
* instead of execl().
*/
#include <stdio.h>
#include <strings.h>
#include <pwd.h>
#include <utmp.h>
#define KEYFILE "/etc/rkeys" /* This file must be read-protected */
main(argc,argv)
int argc;
char *argv[];
{
struct passwd *pp,*getpwnam();
unsigned long t;
FILE *fp;
char name[64];
char key[8];
char work[8];
char answer[8];
char fbuf[64];
char ibuf[64];
char home[64];
char login[64];
char shell[64];
char user[64];
char *keyp;
char *cp,*tty,*ttyname();
int i,ikey[8];
struct utmp utmp;
char *ep[5]; /* we'll build an environment here */
if((fp = fopen(KEYFILE,"r")) == NULL){
printf("Can't open key file\n");
exit(1);
}
/* Get user's name and look it up in the database */
printf("Enter login name: ");
fgets(ibuf,sizeof(ibuf),stdin);
if((cp = index(ibuf,'\n')) != NULL)
*cp = '\0';
strncpy(name,ibuf,sizeof(name));
for(;;){
fgets(fbuf,sizeof(fbuf),fp);
if(feof(fp)){
printf("No key for login name\n");
exit(2);
}
if((cp = index(fbuf,'\n')) != NULL)
*cp = '\0';
if(strncmp(name,fbuf,strlen(name)) == 0)
break;
}
fclose(fp);
/* Find the user's DES key */
if((keyp = index(fbuf,' ')) == NULL){
printf("Missing key field\n");
exit(3);
}
keyp++;
/* Initialize DES with the user's key */
sscanf(keyp,"%2x%2x%2x%2x%2x%2x%2x%2x",
&ikey[0], &ikey[1], &ikey[2], &ikey[3], &ikey[4], &ikey[5],
&ikey[6], &ikey[7]);
for(i=0;i<8;i++)
key[i] = ikey[i];
desinit(0);
setkey(key);
/* Generate and send the challenge */
time(&t);
printf("Challenge: %016x\n",t);
/* Encrypt it locally... */
for(i=0;i<4;i++)
work[i] = 0;
work[4] = t >> 24;
work[5] = t >> 16;
work[6] = t >> 8;
work[7] = t;
endes(work);
/* ...and see if the user can do the same */
printf("Response: ");
for(i=0;i<8;i++){
scanf("%2x",&t);
answer[i] = t;
}
printf("\n"); /* I like it better with a blank line here - bdale */
/* Compare the ciphertexts. If they match, he's in */
for(i=0; i < 8; i++){
if(work[i] != answer[i]){
printf("Wrong response\n");
exit(4);
}
}
if((pp = getpwnam(name)) == NULL){
printf("login name \"%s\" not in /etc/passwd\n",name);
exit(4);
}
if((fp = fopen(UTMP_FILE,"r+")) == NULL){
printf("can't open utmp\n");
exit(4);
}
tty = ttyname(0);
if((cp = rindex(tty,'/')) != NULL)
tty = cp + 1;
while(fread((char *)&utmp,sizeof(struct utmp),1,fp),!feof(fp)){
if(strncmp(utmp.ut_line,tty,8) == 0){
strncpy(utmp.ut_name,name,8);
fseek(fp,(long)-sizeof(struct utmp),1);
fwrite((char *)&utmp,sizeof(struct utmp),1,fp);
break;
}
}
fclose(fp);
chdir(pp->pw_dir);
setregid(pp->pw_gid,pp->pw_gid);
setreuid(pp->pw_uid,pp->pw_uid);
if(pp->pw_shell == NULL || *pp->pw_shell == '\0')
pp->pw_shell = "/bin/ksh";
sprintf(home,"HOME=%s",pp->pw_dir);
sprintf(shell,"SHELL=%s",pp->pw_shell);
sprintf(user,"USER=%s",name);
sprintf(login,"%s/.login",pp->pw_dir);
ep[0] = home;
ep[1] = shell;
ep[2] = user;
ep[3] = (char *) NULL;
execle(pp->pw_shell,"-",0,ep);
printf("Exec failed\n");
}